home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / Tele / C / Comet2.1.3 Folder / Comet / asciidraw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-08  |  28.0 KB  |  1,226 lines  |  [TEXT/MPS ]

  1. /*
  2.     Copyright Cornell University 1986.  All rights are reserved.
  3. */
  4.  
  5. #include <em.h> 
  6. #include <memory.h> 
  7.  
  8. /* Here follow general purpose buffer mod routines for deleting, scrolling, 
  9.     etc. */
  10.  
  11. /* Delete a line at the line # specified in the call 
  12.     calculate scrolling regions if vt100 being used 
  13. */
  14.  
  15. short usedsdraw;            /* OK to use direct to screen drawing */
  16. short emobscured;            /* the window is partially covered, not OK to scroll */
  17. short emupdwait;            /* waiting for update, don't show cursor or scroll */
  18.  
  19. #define PROMPTUPD
  20.  
  21. del_lin(lin)
  22. unsigned int lin;
  23. {
  24.     unsigned char * srcp, * destp;
  25.     unsigned long count;
  26.     short bigsave;
  27.     short bigbotsave;
  28.  
  29.     if (lin == emdp->lastrow) {
  30.         /* kind of unexpected parameter, don't try to scroll! */
  31.         modflg |= modmask[lin];
  32.         c19_blank(emdp->lastline, (int) linelength);
  33.         return;
  34.     }
  35.     if (lin > emdp->lastrow) {
  36.         /* bad arg */
  37.         return;
  38.     }
  39.     
  40.     if (emwindow != NULL && modflg && !emdp->vtjumpscroll) {
  41.         /* !(|| emdp->selrectvis || bkrd_act))   emdp->color || 
  42.         refresh the screen image first */
  43.  
  44.             if (usedsdraw)
  45.                 emrefresh(emwindow, TRUE);
  46.             else
  47.                 (*emdp->screen_upd)();
  48.     }
  49.     /* fix the screen map */
  50.     srcp = emdp->charr + ((lin + 1) * linelength);
  51.     destp = srcp - linelength;
  52.     if (mode == VT100MODE) {
  53.         count = (emdp->scrollbottom - lin) * linelength;
  54.     }
  55.     else {
  56.         count = emdp->charrend - srcp;
  57.     }
  58.  
  59.     if (!emdp->ibm_keymode)
  60.         saveline(destp, linelength);
  61.         /* save the line if needed before it gets overwritten; 
  62.             makes logging scrolling region-based help work swell... */
  63.  
  64.     BlockMove(srcp, destp, count);
  65.     BlockMove(srcp + emdp->screensize, destp + emdp->screensize, count);
  66.     if (mode == VT100MODE) {
  67.         c19_blank(destp + count, (int) linelength);
  68.     }
  69.     else {
  70.         c19_blank(emdp->lastline, (int) linelength);
  71.     }
  72.  
  73.  
  74.     if (emwindow != NULL) {
  75.         /* scroll the screen image */
  76.         
  77.         if (emdp->vtjumpscroll) {
  78.             /* redraw the whole screen later on */
  79.             clrflg = 0;            /* for simplicity's sake */
  80.             while (lin <= emdp->scrollbottom )
  81.                 /* mark modified lines */
  82.                 modflg |= modmask[lin++];
  83.         }
  84.         else if (emdp->selrectvis || bkrd_act || emobscured) {
  85.             /* emdp->color || redraw the whole screen using QD */
  86.             
  87.             clrflg = 0;            /* for simplicity's sake */
  88.             while (lin <= emdp->scrollbottom )
  89.                 /* mark modified lines */
  90.                 modflg |= modmask[lin++];
  91.             
  92.             /* update promptly or wait? currently we wait until another
  93.                 scroll triggers redraw, or wait until screen_service() called
  94.                 if (usedsdraw)
  95.                     emrefresh(emwindow, TRUE);
  96.                 else
  97.                     (*emdp->screen_upd)();
  98.             */
  99.         }
  100.         else {
  101.             /* we can scroll since we're in the foreground */
  102.             if (lin == 0)
  103.                 clrflg >>= 1;
  104.             else
  105.                 clrflg = 0;
  106.                 
  107.             if (usedsdraw) {
  108.                 if ((emdp->scrollbottom - lin) > 0) {
  109.                     clrflg |= modmask[emdp->scrollbottom];        /* show line cleared at bottom */
  110.                     fastscroll(startarr[lin], startarr[lin + 1], emdp->scrollbottom - lin);
  111.                 }
  112.             }
  113.             else {
  114.                 if (mode == VT100MODE) {
  115.                     clrflg |= modmask[emdp->scrollbottom];        /* show line cleared at bottom */
  116.                     emdp->bigrect.bottom = (emdp->scrollbottom + 1) * emdp->lineheight;
  117.                 }
  118.                 else
  119.                     clrflg |= modmask[emdp->lastrow];        /* show line cleared at bottom */
  120.         
  121.                 emdp->bigrect.top = lin * emdp->lineheight + emdp->voffset;
  122.                 ScrollRect(&emdp->bigrect, 0, -emdp->lineheight, updateRgn);
  123.                 emdp->bigrect.top = emdp->voffset;
  124.                 emdp->bigrect.bottom = emdp->bottommarg;
  125.                 if (emdp->color) {
  126.                     paintupdate();
  127.                 }
  128.             }
  129.         }
  130.     }
  131. }
  132.  
  133.  
  134. /* Insert space for a line at the line # specified in the call */
  135.  
  136. ins_lin(lin)
  137. short lin;
  138. {
  139.     unsigned char * srcp, * destp;
  140.     long count;
  141.     short bigsave;
  142.     short bigbotsave;
  143.  
  144.     if (lin == emdp->lastrow) {
  145.         /* kind of unexpected */
  146.         modflg |= modmask[lin];
  147.         c19_blank(emdp->lastline, (int) linelength);
  148.         return;
  149.     }
  150.     if (lin > emdp->lastrow) {
  151.         /* bad arg */
  152.         return;
  153.     }
  154.         
  155.     if (emwindow != NULL && !emdp->vtjumpscroll) {
  156.         /* !(emdp->vtjumpscroll || emdp->selrectvis || bkrd_act)        emdp->color || 
  157.             refresh the screen image first           */
  158.         if (modflg) {
  159.             /* we're using QD & buffer's changed, update screen first */
  160.             if (usedsdraw)
  161.                 emrefresh(emwindow, TRUE);
  162.             else
  163.                 (*emdp->screen_upd)();
  164.         }    
  165.     }
  166.     /* fix the screen map */
  167.     srcp = emdp->charr + (lin * linelength);
  168.     destp = srcp + linelength;
  169.     if (mode == VT100MODE)
  170.         count = (emdp->scrollbottom - lin) * linelength;
  171.     else
  172.         count = emdp->charrend - destp;
  173.     BlockMove(srcp, destp, count);
  174.     BlockMove(srcp + emdp->screensize, destp + emdp->screensize, count);
  175.     c19_blank(srcp, linelength);
  176.  
  177.     if (emwindow != NULL) {
  178.         /* scroll the screen image */
  179.         if (emdp->vtjumpscroll) {
  180.             /* redraw the whole screen later on */
  181.             clrflg = 0;            /* for simplicity's sake */
  182.             while (lin <= emdp->scrollbottom )
  183.                 /* mark modified lines */
  184.                 modflg |= modmask[lin++];
  185.         }
  186.         else if (emdp->selrectvis || bkrd_act || emobscured) {
  187.             /* redraw the whole screen using QD emdp->color || */
  188.             
  189.             clrflg = 0;            /* for simplicity's sake */
  190.             while (lin <= emdp->scrollbottom)
  191.                 /* mark modified lines */
  192.                 modflg |= modmask[lin++];
  193.     
  194.             /* update promptly or wait? 
  195.                 if (usedsdraw)
  196.                     emrefresh(emwindow, TRUE);
  197.                 else
  198.                     (*emdp->screen_upd)();
  199.             */
  200.         }
  201.         else {
  202.             if (lin == 0)
  203.                 clrflg <<= 1;
  204.             else
  205.                 clrflg = 0;
  206.             clrflg |= modmask[lin];            /* set to show line cleared */
  207.             
  208.             if (usedsdraw) {
  209.                 if ((emdp->scrollbottom - lin) > 0) {
  210.                     fastindex(startarr[emdp->scrollbottom], 
  211.                         startarr[emdp->scrollbottom - 1], emdp->scrollbottom - lin);
  212.                 }
  213.             }
  214.             else {
  215.                 if (mode == VT100MODE) {
  216.                     emdp->bigrect.bottom = (emdp->scrollbottom + 1) * emdp->lineheight;
  217.                 }
  218.         
  219.                 emdp->bigrect.top = lin * emdp->lineheight + emdp->voffset;
  220.                 ScrollRect(&emdp->bigrect, 0, emdp->lineheight, updateRgn);
  221.                 emdp->bigrect.top = emdp->voffset;
  222.                 emdp->bigrect.bottom = emdp->bottommarg;
  223.                 if (emdp->color) {
  224.                     paintupdate();
  225.                 }
  226.             }
  227.         }
  228.     }
  229. }
  230.  
  231.  
  232. /* Clear to end of line */
  233.  
  234. /* Shift line over from cursor position to make space for a new character */
  235.  
  236. ins_char()
  237. {
  238.     struct Rect rect;
  239.     unsigned char * srcp;
  240.     unsigned char * destp;
  241.     long count;
  242.  
  243.     if (emwindow != NULL) {
  244.         /* shift the line's screen image over right */
  245.         if (!usedsdraw || emdp->selrectvis || bkrd_act || emobscured) {
  246.             /* redraw the line using QD                had emdp->color || */
  247.             
  248.             modflg |= modmask[ypos];
  249.         }
  250.         else {
  251. #ifdef PROMPTUPD
  252.             if (modflg) {
  253.                 /* we're using QD & buffer's changed, update screen first */
  254.                 if (usedsdraw)
  255.                     emrefresh(emwindow, TRUE);
  256.                 else
  257.                     (*emdp->screen_upd)();
  258.             }    
  259. #endif        
  260.             rect.top = (ypos * emdp->lineheight) + emdp->voffset;
  261.             rect.left = (xpos * fontwidth) + emdp->hoffset;
  262.             rect.bottom = rect.top + emdp->lineheight;
  263.             rect.right = emdp->rightmarg;
  264.             ScrollRect(&rect, fontwidth, 0, updateRgn);
  265.             if (emdp->color) {
  266.                 paintupdate();
  267.             }
  268.         }
  269.     }
  270.     
  271.     /* fix the screen map */
  272.     srcp = charp;
  273.     destp = charp + 1;                /* pointing at next char */
  274.     BlockMove(srcp, destp, (long) (lastcol - xpos));
  275.     BlockMove(srcp + emdp->screensize, destp + emdp->screensize, (long) (lastcol - xpos));
  276.  
  277.     *srcp = ' ';
  278.     *(srcp + emdp->screensize) = 0;    /* clear the new space */
  279.  
  280. }
  281.  
  282.  
  283. /* Delete the character at the cursor position */
  284.  
  285. del_char()
  286. {
  287.     struct Rect rect;
  288.     unsigned char * srcp; 
  289.     unsigned char * destp;
  290.     long count;
  291.  
  292.     if (emwindow != NULL) {
  293.         /* scroll the screen image */
  294.         if (!usedsdraw || emdp->selrectvis || bkrd_act || emobscured) {
  295.             /* redraw the whole screen using QD emdp->color || */
  296.             
  297.             modflg |= modmask[ypos];
  298.         }
  299.         else {
  300. #ifdef PROMPTUPD
  301.             if (modflg) {
  302.                 /* we're using QD & buffer's changed, update screen first */
  303.                 if (usedsdraw)
  304.                     emrefresh(emwindow, TRUE);
  305.                 else
  306.                     (*emdp->screen_upd)();
  307.             }    
  308. #endif        
  309.             rect.top = ypos * emdp->lineheight + emdp->voffset;
  310.             rect.left = (xpos * fontwidth) + emdp->hoffset;
  311.             rect.bottom = rect.top + emdp->lineheight;
  312.             rect.right = emdp->rightmarg;
  313.             ScrollRect(&rect, -fontwidth, 0, updateRgn);
  314.             if (emdp->color) {
  315.                 paintupdate();
  316.             }
  317.         }
  318.     }
  319.     /* fix the screen map */
  320.     srcp = charp + 1;                /* pointing at next char */
  321.     destp = charp;
  322.     count = (lastcol - xpos);
  323.     BlockMove(srcp, destp, count);
  324.     BlockMove(srcp + emdp->screensize, destp + emdp->screensize, count);
  325.  
  326.     destp += count;                    
  327.     *(destp) = ' ';                /* blank out the last char */
  328.     *(destp + emdp->screensize) = 0;    /* blank attibute */
  329.     
  330. }
  331.  
  332. /* clear line from cursor to end of line */
  333.  
  334. clr_eol()
  335. {
  336.     struct Rect rect;
  337.     long count;
  338.  
  339.     if (emwindow != NULL) {
  340.         if (emdp->selrectvis || bkrd_act || emupdwait || emobscured) {
  341.             /* must redraw through upd 'emdp->color' */
  342.             modflg |= modmask[ypos];
  343.         }
  344.         else {
  345.             /* clear the screen image; can do in bkrd */
  346.             rect.top = ypos * emdp->lineheight + emdp->voffset;
  347.             rect.left = xpos * fontwidth + emdp->hoffset;
  348.             rect.bottom = rect.top + emdp->lineheight;
  349.             rect.right = emdp->rightmarg;
  350.             clearrect(&rect);
  351.         }
  352.     }
  353.     if ((emdp->logerase || xpos == 0) && !emdp->ibm_keymode )
  354.         saveline(charp, linelength);
  355.             /* save WHOLE line if needed before it gets overwritten */
  356.  
  357.     /* fix the screen map */
  358.     c19_blank(charp, (linelength - xpos));
  359. }
  360.  
  361.  
  362. /* erase line up to and including cursor position */
  363.  
  364. clrtocurs()
  365. {
  366.     Rect temprect;
  367.     unsigned char * srcp;
  368.  
  369.     if (emwindow != NULL) {
  370.         if (emdp->selrectvis || bkrd_act || emupdwait || emobscured) {
  371.             /* must redraw through upd emdp->color */
  372.             modflg |= modmask[ypos];
  373.         }
  374.         else {
  375.             /* erase the screen image */
  376.             temprect.top = ypos * emdp->lineheight + emdp->voffset;
  377.             temprect.left = emdp->hoffset;
  378.             temprect.bottom = temprect.top + emdp->lineheight;
  379.             temprect.right = (xpos + 1) * fontwidth + emdp->hoffset;
  380.     
  381.             clearrect(&temprect);
  382.         }
  383.     }
  384.     /* fix the screen map */
  385.     srcp = charp - xpos;
  386.  
  387.     if ((emdp->logerase || xpos == lastcol) && !emdp->ibm_keymode)
  388.         saveline(srcp, linelength);
  389.             /* save the line if needed before it gets overwritten */
  390.  
  391.     c19_blank(srcp, xpos + 1);
  392.  
  393. }
  394.  
  395.  
  396. /* general drawing routines */
  397.  
  398. emprep()
  399. {
  400.     if (emwindow == NULL)
  401.         return;
  402.         
  403.     ++inemulator;
  404.  
  405.     if (emdp->dsdraw && !bkrd_act && dsdrawok()) {
  406.         /* set the flag to show everything is ok to use dsdraw */
  407.         usedsdraw = TRUE;
  408.     }
  409.     else {
  410.         usedsdraw = FALSE;
  411.     }
  412.     if (usedsdraw && mousecurson) {
  413.         ShieldCursor(&emdp->zaprect, 0L);
  414.             /* long not really legit: pass(Point(0,0)) or pass(topLeft(emwindow->portRect)) */
  415.         /* HideCursor(); */
  416.         mousecurson = FALSE;
  417.     }
  418.  
  419.     if (updatewait()) {
  420.         /* do nothing if an update is pending */
  421.         /* TODO what about updatewait() ?  does it need to be called 
  422.             intermittently to keep screen posters
  423.             such as QuickMail Conferencing from producing turds? */
  424.  
  425.         emupdwait = TRUE;
  426.         usedsdraw = FALSE;            /* make sure chars don't appear promptly */
  427.     }
  428.     else {
  429.         emupdwait = FALSE;
  430.         if (emdp->curson) {
  431.             /* if cursor visible, invert it */
  432.             InvertRect(&emdp->cursrect);
  433.             emdp->curson = FALSE;
  434.         }
  435.         if (trackon && emdp == keydp) {
  436.             InvertRect(&mouserect);
  437.             trackon = FALSE;
  438.         }
  439.     }
  440.     emtestvis();
  441. }
  442.  
  443. emend()
  444. {
  445.     if (emwindow == NULL)
  446.         return;
  447.         
  448.     --inemulator;
  449.     if (usedsdraw) {
  450.         if (!mousecurson) {
  451.             /* if (!mfbackground)
  452.                 ObscureCursor();            
  453.                 hide until next motion; incompatible with ShieldCursor */
  454.             ShowCursor();
  455.             mousecurson = TRUE;
  456.         }
  457.     }
  458.     else if (!mousecurson) {
  459.         ShowCursor();
  460.         mousecurson = TRUE;
  461.     }
  462. }
  463.  
  464.  
  465. /* drawing routines for direct-to-screen algorithm */
  466.  
  467. /*
  468.  * Redraw the window frame screen contents from the screen map in charr[]
  469.  * (called on updateEvt)
  470.  *
  471.  */
  472.  
  473.  
  474. emrefresh(emwindow, doinvert)
  475. WindowPtr emwindow;
  476. short doinvert;
  477. {
  478.     register unsigned char * chp;
  479.     register unsigned char * attp;
  480.     register unsigned char curattr;
  481.     register short notstart;                /* # chars to start of invert range */
  482.     register short notcount;                /* # chars within invert range */
  483.     register unsigned long linemod;
  484.     register unsigned long lineclr;
  485.     short oldx, oldy;
  486.     FONTS *oldfont;
  487.     GrafPtr oldport;
  488.     char zapped = FALSE;
  489.     short textmode;                        /* current text mode */
  490.     short ozapinvert;
  491.     short ozapuline;
  492.     
  493.     if (emwindow == NULL)
  494.         return;
  495.         
  496.     if (bkrd_act || !dsdrawok()) {
  497.         paintbuf(&emdp->charr[0], doinvert);
  498.         return;
  499.     }
  500.  
  501.     GetPort(&oldport);
  502.     SetPort(emwindow);
  503.  
  504.     inselection = FALSE;
  505.     ozapinvert = zapinvert;        /* save current state */
  506.     ozapuline = zapuline;
  507.     if (doinvert) {
  508.         if (emdp->selrectvis) {
  509.             /* calculate character range over which we use notSrcCopy */
  510.             notstart = emdp->selystart * linelength + emdp->selxstart;
  511.             notcount = emdp->selyend * linelength + emdp->selxend - notstart;
  512.             if (notcount == 0) {
  513.                 doinvert = FALSE;
  514.             }
  515.             else if (notstart == 0)
  516.                 inselection = TRUE;
  517.         }
  518.         else 
  519.             doinvert = FALSE;
  520.     }
  521.     
  522.     oldx = xpos;
  523.     oldy = ypos;
  524.     oldfont = thefont;
  525.  
  526.     /* fill screen */
  527.     chp = emdp->charr;
  528.     attp = chp + emdp->screensize;
  529.     curattr = TRUE;                /* force attr set on first round */
  530.  
  531.     /* xpos & ypos need to be set for zapchar */
  532.     for (ypos = 0; ypos <= emdp->lastrow; ++ypos) {
  533.         linemod = modflg & modmask[ypos];
  534.         lineclr = clrflg & modmask[ypos];
  535.         for (xpos = 0; xpos <= lastcol; ++xpos, ++chp, ++attp) {
  536.             if (doinvert) {
  537.                 /* check to see if we're in the selection range */
  538.                 if (notstart-- == 0) {
  539.                     /* we just entered the range */
  540.                     curattr = TRUE;
  541.                         /* we presume no attr can be all TRUE */
  542.                     inselection = TRUE;
  543.                 }
  544.                 if (notstart < 0) {
  545.                     /* we have entered the range */
  546.                     if (notcount-- == 0) {
  547.                         /* we just left it */
  548.                         curattr = TRUE;
  549.                         doinvert = FALSE;
  550.                         inselection = FALSE;
  551.                     }
  552.                 }
  553.             }
  554.             if (!linemod)
  555.                 /* no need to check attributes or draw if line not modified */
  556.                 continue;
  557.                 
  558.             if (*attp != curattr) {
  559.                 curattr = *attp;
  560.  
  561.                 /* set the font display mode */
  562.                 setascattr_ds(curattr, inselection);
  563.             }
  564.             if (lineclr && skiparr[*chp] && !zapuline && !zapinvert)
  565.                 /* we don't need to draw blanks */
  566.                 continue;
  567.  
  568.             zapchar(*chp);
  569.             zapped = TRUE;
  570.         }
  571.         if (zapped) {
  572.             clrflg &= ~modmask[ypos];        /* reset clear flag */
  573.             zapped = FALSE;
  574.         }
  575.     }
  576.  
  577.     /* reset font */
  578.     zapinvert = ozapinvert;
  579.     zapuline = ozapuline;
  580.     thefont = oldfont;
  581.     xpos = oldx;
  582.     ypos = oldy;
  583.  
  584.     modflg = 0;
  585.     SetPort(oldport);
  586. }
  587.  
  588.  
  589. /* scroll the screen image */
  590.  
  591. scrollup_ds()
  592. {
  593.     struct winds * owp;
  594.     EventRecord anevent;
  595.     
  596.     if (bkrd_act || !dsdrawok()) {
  597.         /* use QD scroll call before logsession etc. */
  598.         
  599.         scrollup_qd();
  600.         return;
  601.     }
  602.  
  603. #ifdef SUICIDAL    
  604. /* the background service stuff here is very dangerous... */
  605.     /* check to see if user wants to stop */
  606.     if (emdp->scrollcount++ > 8) {
  607.         owp = emdp;
  608.         
  609.         emdp->scrollcount = 0;
  610.         ++bkrd_act;
  611.         do {
  612.             /* TODO should call bkrd_service && block out current window??? */
  613.             user_act();
  614.             maccursor(TRUE);    /* move the cursor without tracking in emulator */
  615.         }
  616.         while (emdp->userxoff);
  617.         if (bkrd_act > 0)
  618.             --bkrd_act;
  619.         getcontext(owp);
  620.             /* restore the old context, will fix port after maccursor */
  621.             
  622.         /* scrolling up yields, make sure dsdraw still valid */
  623.         if (emdp->dsdraw && !bkrd_act && dsdrawok()) {
  624.             usedsdraw = TRUE;
  625.         }
  626.         else {
  627.             usedsdraw = FALSE;
  628.         }
  629.         if (usedsdraw) {
  630.             /* could be we're behind something now... */
  631.             scrollup_qd();
  632.             return;
  633.         }
  634.     }
  635. #else
  636.     /* user has sent ^S; hang until keystroke or mouseclik  */
  637.         if (emdp->userxoff) {
  638.             while (TRUE) {
  639.                 if (EventAvail(keyDownMask | mDownMask, &anevent))
  640.                     break;
  641.             }
  642.         }
  643.     
  644. #endif        
  645.     if (emwindow != NULL) {
  646.         /* update the screen */
  647.         if (emdp->vtjumpscroll || emupdwait) {
  648.             /* wait to draw the screen */
  649.             modflg = SCRALLMOD;
  650.         }
  651.         else if (emdp->selrectvis) {
  652.             /* don't scroll the selection, redraw the whole screen using ds update */
  653.             modflg = SCRALLMOD;
  654.         }
  655.         else {
  656.             /* erase the cursor, which won't be picked up by scroll routine  */
  657.             if (emdp->curson) {
  658.                 InvertRect(&emdp->cursrect);
  659.                 emdp->curson = FALSE;
  660.             }
  661.             if (modflg) {
  662.                 /* update before scroll */
  663.                 emrefresh(emwindow, TRUE);
  664.             }
  665.             modflg >>= 1;                /* shift modified flags right */
  666.             clrflg >>= 1;                /* shift clear flags right */
  667.             clrflg |= modmask[emdp->lastrow];        /* show line cleared at bottom */
  668.             
  669.             fastscroll(startarr[0], startarr[1], emdp->lastrow);
  670.         }
  671.     }    
  672.     saveline(&emdp->charr[0], linelength);
  673.         /* save the line if needed before it gets overwritten */
  674.  
  675.     /* take care of screen map */
  676.     BlockMove(emdp->secondline, &emdp->charr[0], emdp->size23);
  677.     BlockMove(emdp->secondline + emdp->screensize, &emdp->charr[0] + emdp->screensize, emdp->size23);
  678.     c19_blank(emdp->lastline, linelength);
  679.  
  680.     if (emwindow && emdp->selrectvis) {
  681.         /* display the updated screen promptly */
  682.         emrefresh(emwindow, TRUE);
  683.     }
  684.     
  685.     return(0);
  686. }
  687.  
  688.  
  689.  
  690. /* quickdraw version of the drawing routines */
  691.  
  692. paintbuf(scrbuf, doinvert)
  693. unsigned char * scrbuf;
  694. short doinvert;
  695. {
  696.     register unsigned char * textp; 
  697.     register unsigned char * drawstart;
  698.     register unsigned char * lineend;
  699.     register unsigned char * attp;
  700.     register unsigned char attr;
  701.     register short notstart;                /* # chars to start of invert range */
  702.     register short notcount;                /* # chars within invert range */
  703. #ifdef SKIPBLANKS
  704.     register short blanks = 0;    /* # blanks not to draw */
  705. #endif
  706.     register unsigned long linemod;
  707.     register unsigned long lineclr;
  708.  
  709.     short drawcount;
  710.     char zapped = FALSE;
  711.  
  712.     short yloc;
  713.     short linecount;
  714.     unsigned char inselection;            /* in selection range */
  715.     short textmode;                        /* current text mode */
  716.  
  717.     
  718.     if (emwindow == NULL)
  719.         return;
  720.  
  721.     yloc = emdp->lineheight - emdp->fontdescent + emdp->voffset;        /* pen vert pos */
  722.     textp = drawstart = scrbuf;
  723.  
  724. /* find and set current attribute */
  725.     attp = scrbuf + emdp->screensize;
  726.     attr = *attp;
  727.  
  728.     inselection = FALSE;
  729.     if (doinvert) {
  730.         if (emdp->selrectvis) {
  731.             /* calculate character range over which we use notSrcCopy */
  732.             notstart = emdp->selystart * linelength + emdp->selxstart;
  733.             notcount = emdp->selyend * linelength + emdp->selxend - notstart;
  734.             if (notcount == 0) {
  735.                 doinvert = FALSE;
  736.             }
  737.             else if (notstart == 0)
  738.                 inselection = TRUE;
  739.         }
  740.         else 
  741.             doinvert = FALSE;
  742.     }
  743.     attr = TRUE;            /* force attribute setting first time around */
  744.  
  745.     lineend = textp + linelength;
  746.     for (linecount = 0; linecount <= emdp->lastrow; linecount++, lineend += linelength) {
  747.         linemod = modflg & modmask[linecount];
  748.         lineclr = clrflg & modmask[linecount];
  749.         
  750.         if (linemod)
  751.             MoveTo(emdp->hoffset, yloc);
  752.         for ( ; textp < lineend; textp++, attp++) {
  753.             if (doinvert) {
  754.                 /* check to see if we're in the selection range */
  755.                 if (notstart-- == 0) {
  756.                     /* we just entered the range */
  757.                     attr = TRUE;
  758.                     inselection = TRUE;
  759.                 }
  760.                 if (notstart < 0) {
  761.                     /* we have entered the range */
  762.                     if (notcount-- == 0) {
  763.                         /* we just left it */
  764.                         inselection = FALSE;
  765.                         attr = TRUE;
  766.                         doinvert = FALSE;
  767.                     }
  768.                 }
  769.             }
  770.             if (! linemod) {
  771.                 /* no need to check attributes if we're not drawing */
  772.                 continue;
  773.             }
  774.             if (*attp != attr) {
  775.                 /* we hit a new attribute, draw a string now */
  776.  
  777. #ifdef SKIPBLANKS
  778.                 drawcount = textp - drawstart - blanks;
  779.                 if (drawcount > 0) {
  780.                     DrawText(drawstart, 0, drawcount);
  781.                     zapped = TRUE;
  782.                 }
  783.                 if (blanks) {
  784.                     /* skip them */
  785.                     Move(blanks * fontwidth, 0);
  786.                     blanks = 0;
  787.                 }
  788. #else
  789.                 DrawText(drawstart, 0, textp - drawstart);
  790. #endif
  791.                 drawstart = textp;
  792.                 if (attr == TRUE) {
  793.                     /* could be transiting selection range, set new mode & reset flag */
  794.                     if (notstart == -1) {
  795.                         /* just entered the range */
  796.                         inselection = TRUE;
  797.                     }
  798.                     else if (notcount == -1) {
  799.                         inselection = FALSE;
  800.                     }
  801.                 }
  802.  
  803.                 /* set the font type */
  804.                 attr = *attp;
  805.                 textmode = setascattr_qd(attr, inselection);
  806.             }
  807. #ifdef SKIPBLANKS
  808.             if (!emdp->color && lineclr) {
  809.                 if (skiparr[*textp] && textmode == srcCopy) {
  810.                     /* add up consecutive blanks at right end */
  811.                     blanks++;
  812.                 }
  813.                 else if (blanks > 2) {
  814.                     /* we'll break up line into smaller frags but will skip more
  815.                         spaces, an OK trade? */
  816.                     --textp;        /* back up to catch this char again */
  817.                     --attp;
  818.                     attr = TRUE;
  819.                 }
  820.                 else
  821.                     blanks = 0;
  822.             }
  823. #endif
  824.         }
  825.         if (linemod && drawstart < lineend) {
  826.             /* avoid problems with attribute at end of line */
  827.             drawcount = textp - drawstart - blanks;
  828.             if (drawcount > 0) {
  829.                 DrawText(drawstart, 0, drawcount);
  830.                 zapped = TRUE;
  831.             }
  832.         }
  833.         if (zapped) {
  834.             clrflg &= ~modmask[linecount];        /* reset clear flag */
  835.             zapped = FALSE;
  836.         }
  837.         blanks = 0;
  838.         drawstart = lineend;
  839.         yloc += emdp->lineheight;
  840.             /* fix for the next time around */
  841.     }
  842.     TextMode(srcCopy);
  843.     TextFace(0);        /* return to normal font style */
  844.     modflg = 0;
  845. }
  846.  
  847.  
  848. /* quickdraw routine to draw a character on the screen */
  849.  
  850. ch_draw_qd(thechar)
  851. register char thechar; 
  852. {
  853.     short offset;
  854.     short oldfont;
  855.     GrafPtr oldport;
  856.     short notstart, notcount, thispos;
  857.     char inselection;
  858.     Rect chinvrect;
  859.     
  860.     if (emwindow == NULL)
  861.         return;
  862.  
  863.     GetPort(&oldport);
  864.     SetPort(emwindow);
  865.  
  866.     oldfont = emwindow->txFont;
  867.  
  868.     inselection = chkinvert();
  869.  
  870.     TextSize(emdp->fontsize);
  871.     
  872.     setascattr_qd(attrib, inselection);
  873.  
  874.     /* do it */
  875.  
  876.     chinvrect.top = ypos * emdp->lineheight + emdp->voffset;
  877.     chinvrect.left = xpos * fontwidth + emdp->hoffset;
  878.  
  879.     MoveTo(chinvrect.left, chinvrect.top + emdp->lineheight - emdp->fontdescent);
  880.     DrawChar(thechar);
  881.  
  882.     /* endibmdraw_qd(); */
  883.  
  884.     if (inselection) {
  885.         if (emdp->color) {
  886.             /* invert the newly drawn character */
  887.             chinvrect.bottom = chinvrect.top + emdp->fontheight;    /* - 2 skipped by zap */
  888.             chinvrect.right = chinvrect.left + emdp->fontwidth;
  889.             
  890.             InvertRect(&chinvrect);
  891.         }
  892.         else
  893.             TextMode(srcCopy);
  894.     }
  895.     TextFace(0);
  896.     TextFont(oldfont);
  897.     SetPort(oldport);
  898.     if (emdp->color) {
  899.         BackColor((long) whiteColor);
  900.         ForeColor((long) blackColor);
  901.     }
  902. }
  903.  
  904.  
  905. /* A portable routine to scroll up the emulator screen up one line,
  906.     as fast as possible
  907. */
  908.  
  909. scrollup_qd()
  910. {
  911.     short bigsave;
  912.     RgnHandle oldclip;
  913.     struct winds * owp;
  914.     EventRecord anevent;
  915.     
  916. #ifdef SUICIDAL    
  917. /* the background service stuff here is very dangerous... */
  918.     /* check to see if user wants to stop */
  919.     if (emdp->scrollcount++ > 8) {
  920.         emdp->scrollcount = 0;
  921.         ++bkrd_act;
  922.         owp = emdp;
  923.         do {
  924.             user_act();
  925.             maccursor(TRUE);    /* move the cursor without tracking in emulator */
  926.         }
  927.         while (emdp->userxoff);
  928.         if (bkrd_act > 0)
  929.             --bkrd_act;
  930.         getcontext(owp);
  931.             /* restore the old context */
  932.     }
  933. #else
  934.     /* user has sent ^S; hang until keystroke or mouseclik */
  935.         if (emdp->userxoff) {
  936.             while (TRUE) {
  937.                 if (EventAvail(keyDownMask | mDownMask, &anevent))
  938.                     break;
  939.             }
  940.         }
  941.      
  942. #endif
  943.  
  944.     if (emwindow != NULL && modflg &&
  945.         !(emdp->vtjumpscroll || emdp->selrectvis || bkrd_act || emupdwait || emobscured)) {
  946.             /* we're using QD & buffer's changed, update screen before ScrollRect */
  947.             (*emdp->screen_upd)();
  948.     }
  949.  
  950.     saveline(&emdp->charr[0], linelength);
  951.         /* save the line if needed before it gets overwritten */
  952.  
  953.     /* take care of screen map */
  954.     BlockMove(emdp->secondline, &emdp->charr[0], emdp->size23);
  955.     BlockMove(emdp->secondline + emdp->screensize, &emdp->charr[0] + emdp->screensize, emdp->size23);
  956.     c19_blank(emdp->lastline, linelength);
  957.  
  958.     if (emwindow == NULL)
  959.         return;
  960.  
  961.     /* scroll the screen image */
  962.     if (emupdwait || emdp->vtjumpscroll) {
  963.         /* redraw the whole screen later on */
  964.         modflg = SCRALLMOD;
  965.     }
  966.     else if (emdp->selrectvis || bkrd_act || emobscured) {
  967.         /* redraw the whole screen using QD || emdp->color */
  968.         modflg = SCRALLMOD;
  969.         (*emdp->screen_upd)();
  970.     }
  971. #ifdef THISWORKS
  972.     /* alas, this doesn't work; seems to mess things up for some reason */
  973.     else if (bkrd_act) {
  974.         /* ought to scroll & redraw the just updateRgn using QD */
  975.         /* reset clip to area we're drawing in  */
  976.         oldclip = NewRgn();
  977.         GetClip(oldclip);
  978.     
  979.         modflg >>= 1;                /* shift modified flags right */
  980.         clrflg >>= 1;                /* shift clear flags right */
  981.         ScrollRect(&emdp->bigrect, 0, -emdp->lineheight, updateRgn);
  982.         clrflg |= modmask[emdp->lastrow];        /* show line cleared at bottom */
  983.  
  984.         SetClip(updateRgn);
  985.         
  986.         modflg = SCRALLMOD;
  987.         (*emdp->screen_upd)();
  988.         
  989.         SetClip(oldclip);
  990.         DisposeRgn(oldclip);        
  991.     }
  992. #endif
  993.     else {
  994.         modflg >>= 1;                /* shift modified flags right */
  995.         clrflg >>= 1;                /* shift clear flags right */
  996.         clrflg |= modmask[emdp->lastrow];        /* show line cleared at bottom */
  997.  
  998.         ScrollRect(&emdp->bigrect, 0, -emdp->lineheight, updateRgn);
  999.         if (emdp->color) {
  1000.             paintupdate();
  1001.         }
  1002.     }
  1003. }
  1004.  
  1005. #define ATNORM        0
  1006. #define ATNORMREV    2
  1007. #define ATBOLD        4
  1008. #define ATBOLDREV    6
  1009.  
  1010. #define ATBLINK        8
  1011.  
  1012. #define ATFORE        0
  1013. #define ATBACK        1
  1014.  
  1015. setascattr_qd(attrib, inselection)
  1016. unsigned char attrib;
  1017. int inselection;
  1018. {
  1019.     int textmode;                /* drawing mode of pen */
  1020.     int field = ATNORM;
  1021.     
  1022.     if (emwindow == NULL)
  1023.         return;
  1024.  
  1025. #ifndef MERGEDVTCHARS
  1026.     /* set the font type */
  1027.     if (attrib & VTFONT)
  1028.         TextFont(emdp->vtfont);
  1029.     else
  1030. #endif
  1031.         TextFont(emdp->normfont);
  1032.  
  1033.     /* set the font display mode */
  1034.     TextFace(0);
  1035.     textmode = (inselection ? notSrcCopy : srcCopy);
  1036.  
  1037.     if (attrib & REVERSE) {
  1038.         textmode = (inselection ? srcCopy : notSrcCopy);
  1039.             /* in selection range, reversed reverse! */
  1040.  
  1041.         if (!inselection)
  1042.             /* make the field a reverse color */
  1043.             field = ATNORMREV;
  1044.     }
  1045.     if (attrib & UNDERSCORE) {
  1046.         TextFace(underlineStyle);
  1047.     }
  1048.     if (attrib & BLINK) {
  1049.         /* only works in color */
  1050.         field += ATBLINK;
  1051.     }
  1052.     if (attrib & BOLD) {
  1053.         field += ATBOLD;
  1054. #ifndef MERGEDVTCHARS
  1055.         if (! (attrib & VTFONT))
  1056. #endif
  1057.             TextFont(emdp->highfont);
  1058.     }
  1059.     if (emdp->color) {
  1060.         RGBForeColor(&emdp->colormap.colors[field]);
  1061.         RGBBackColor(&emdp->colormap.colors[field + ATBACK]);
  1062.     }
  1063.     else
  1064.         TextMode(textmode);
  1065.         
  1066.     return(textmode);
  1067. }    
  1068.  
  1069.  
  1070. paintupdate()
  1071. {
  1072.     /* fill in the new space with the norm bkrd color */
  1073.     RGBColor forecolor;
  1074.     
  1075.     if (usedsdraw)
  1076.         return;
  1077.         
  1078.     GetForeColor(&forecolor);
  1079.     
  1080.     RGBForeColor(&emdp->colormap.colors[1]);        /* normal background */
  1081.     PaintRect(&((*updateRgn)->rgnBBox));
  1082.     RGBForeColor(&forecolor);
  1083. }
  1084.  
  1085.  
  1086. /* just in case BlockMove doesn't work ..... */
  1087.  
  1088. myBlockMove(source, dest, length)
  1089. char * source;
  1090. char * dest;
  1091. long length;
  1092. {
  1093.     length++;
  1094.     if (source > dest) {
  1095.         while (--length) {
  1096.             *dest++ = *source++;
  1097.         }
  1098.     }
  1099.     else {
  1100.         /* make sure overlapping block handled OK */
  1101.         source += length;
  1102.         dest += length;
  1103.         while (--length) {
  1104.             *--dest = *--source;
  1105.         }
  1106.     }
  1107. }
  1108.  
  1109.  
  1110. /* set the direct to screen font * to reflect the current attribute */
  1111.  
  1112. setascattr_ds(attrib, inselection)
  1113. register unsigned char attrib;
  1114. register short inselection;
  1115. {
  1116.     
  1117.     if (emdp->dsdraw) {
  1118. #ifndef MERGEDVTCHARS
  1119.         if (attrib & VTFONT) {
  1120.                 /* doesn't handle bold */
  1121.             if (attrib & REVERSE) {
  1122.                 thefont = (inselection ? &bvtfont : &invbvtfont);
  1123.                     /* in selection range, reversed reverse! */
  1124.             }
  1125.             else 
  1126.                 thefont = (inselection ? &invbvtfont : &bvtfont);
  1127.         }
  1128.         else 
  1129. #endif
  1130.         {
  1131.             if (attrib & REVERSE) {
  1132.                 /* in selection range, reversed reverse! */
  1133.                 if (attrib & BOLD) {
  1134.                     thefont = (inselection ? &boldfont : &invboldfont);
  1135.                 }
  1136.                 else {
  1137.                     thefont = (inselection ? &font : &invfont);
  1138.                 }
  1139.             } 
  1140.             else if (attrib & BOLD) {
  1141.                 thefont = (inselection ? &invboldfont : &boldfont);
  1142.             }
  1143.             else
  1144.                 thefont = (inselection ? &invfont : &font);
  1145.         }    
  1146.         if (attrib & UNDERSCORE) {
  1147.             zapuline = TRUE;
  1148.         }
  1149.         else {
  1150.             zapuline = FALSE;
  1151.         }
  1152.         if (thefont == &invfont 
  1153.                 || thefont == &invboldfont 
  1154. #ifndef MERGEDVTCHARS
  1155.                 || thefont == &invbvtfont
  1156. #endif
  1157.             )
  1158.             zapinvert = TRUE;
  1159.         else
  1160.             zapinvert = FALSE;
  1161. #ifdef BITSUPPORT
  1162.         if (attrib & BLINK) {
  1163.             /* ??? what should be done ? */
  1164.             TextMode(inselection ? srcCopy : notSrcCopy);
  1165.         }
  1166. #endif
  1167.     }
  1168. }
  1169.  
  1170.  
  1171. /* clear a rectangle, paint the background if colored */
  1172.  
  1173. clearrect(rectp)
  1174. Rect * rectp;
  1175. {
  1176.     RGBColor forecolor;
  1177.  
  1178. #ifdef PROMPTUPD
  1179.     if (modflg) {
  1180.         /* we're using QD & buffer's changed, update screen first */
  1181.         if (usedsdraw)
  1182.             emrefresh(emwindow, TRUE);
  1183.         else
  1184.             (*emdp->screen_upd)();
  1185.     }    
  1186. #endif        
  1187.     if (emdp->color) {
  1188.         GetForeColor(&forecolor);
  1189.         
  1190.         RGBForeColor(&emdp->colormap.colors[1]);        /* normal background */
  1191.         PaintRect(rectp);
  1192.         RGBForeColor(&forecolor);
  1193.     }
  1194.     else {
  1195.         EraseRect(rectp);
  1196.     }
  1197. }
  1198.  
  1199.  
  1200. /* check the visible region of the window to see whether other windows 
  1201.     overlap, which means we must refresh entire screen */
  1202.  
  1203. emtestvis()
  1204. {
  1205.     Rect intersect;
  1206.     RgnPtr visptr = (*emwindow->visRgn);
  1207.  
  1208.     if (emwindow == FrontWindow() && 
  1209.             (emdp->gdRect.bottom == 342)
  1210.             || (emdp->fontsize == 16 && emdp->gdRect.bottom == 480)
  1211.                 ) {
  1212.             /* we're on a small screen & the emulator area is completely visible;
  1213.                 on small screens it will be vis since not movable,
  1214.                 but there's a real rgn due to the round corners added
  1215.                 by the stupid screen interface so the following test will fail.... */
  1216.         emobscured = FALSE;
  1217.     }
  1218.     else if (visptr->rgnSize == 10
  1219.                 && SectRect(&emdp->bigrect, &visptr->rgnBBox, &intersect)
  1220.                 && EqualRect(&emdp->bigrect, &intersect)) {
  1221.             /* the emulator area is completely visible */
  1222.         emobscured = FALSE;
  1223.     }
  1224.     else
  1225.         emobscured = TRUE;
  1226. }